package com.ma.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ma.auth.mapper.SysMenuMapper;
import com.ma.auth.service.SysMenuService;
import com.ma.auth.service.SysRoleMenuService;
import com.ma.auth.utils.MenuHelper;
import com.ma.common.config.exception.MaException;
import com.ma.model.system.SysMenu;
import com.ma.model.system.SysRoleMenu;
import com.ma.vo.system.AssginMenuVo;
import com.ma.vo.system.MetaVo;
import com.ma.vo.system.RouterVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    @Autowired
    private SysRoleMenuService roleMenuService;
    @Override
    public List<SysMenu> findNodes() {
        List<SysMenu> sysMenus = baseMapper.selectList(null);
        return MenuHelper.buildTree(sysMenus);
    }

    @Override
    public void removeMenuById(Long id) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getParentId,id);
        Integer count = baseMapper.selectCount(wrapper);
        if(count > 0){
            throw new MaException(201,"菜单存在下级目录，不能删除");
        }
        baseMapper.deleteById(id);
    }

    @Override
    public List<SysMenu> findMenuByRoleId(Long roleId) {
        //获取全部菜单列表
        List<SysMenu> allSysMenuList = this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus,1));
        //根据角色id获取菜单id
        List<SysRoleMenu> sysRoleMenuList = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId,roleId));
        List<Long> menuId = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        //将菜单id和所有菜单列表id进行比对，存在将isSelect字段设置为true
        for (SysMenu sysMenu : allSysMenuList){
            sysMenu.setSelect(menuId.contains(sysMenu.getId()));
        }
        //返回规定形式的树形结构
        List<SysMenu> treeMenu = MenuHelper.buildTree(allSysMenuList);
        return treeMenu;

    }

    //为角色分配菜单
    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        //根据角色id，删除角色菜单表里面分配过的菜单
        Long roleId = assginMenuVo.getRoleId();
        roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId,roleId));
        //将新的菜单分配给角色
        List<Long> menuIdList = assginMenuVo.getMenuIdList();
        for(Long menuId : menuIdList){
            if (StringUtils.isEmpty(menuId)){
                continue;
            }
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenu.setRoleId(roleId);
            roleMenuService.save(sysRoleMenu);
        }
    }

    @Override
    public List<RouterVo> findUserMenuByUserId(Long userId) {
        List<SysMenu> sysMenuList = null;
        //1.判断用户是否是管理员 userID = 1即为管理员
        if (userId == 1){
            //若是管理员则查询所有菜单列表
            sysMenuList = this.list(new LambdaQueryWrapper<SysMenu>()
                                    .eq(SysMenu::getStatus,1)
                                    .orderByAsc(SysMenu::getSortValue));
        }else {
            //2.不是管理员，根据userid查询菜单列表
            //多表关联查询，用户角色关系表，角色菜单关系表，菜单表
            sysMenuList = baseMapper.findMenuListByUserId(userId);


        }
        //3.把查询出来的数据列表构建成要求的路由数据结构
        //使用菜单操作工具类构建成树形结构
        List<SysMenu> sysMenuTree = MenuHelper.buildTree(sysMenuList);
        //构建成要求的路由数据结构
        List<RouterVo> routerList = this.buildRouter(sysMenuTree);
        return routerList;
    }

    //构建成要求的路由数据结构
    private List<RouterVo> buildRouter(List<SysMenu> sysMenuTree) {
        //创建list集合，存储最终数据
        List<RouterVo> routers = new ArrayList<>();
        //遍历sysMenuTree
        for(SysMenu sysMenu : sysMenuTree){
            RouterVo routerVo = new RouterVo();
            routerVo.setHidden(false);
            routerVo.setAlwaysShow(false);
            routerVo.setPath(getRouterPath(sysMenu));
            routerVo.setComponent(sysMenu.getComponent());
            routerVo.setMeta(new MetaVo(sysMenu.getName(),sysMenu.getIcon()));
            //下一层数据部分
            List<SysMenu> children = sysMenu.getChildren();
            if (sysMenu.getType() == 1){ //表示菜单层级
                //加载出来下面的隐藏路由
                List<SysMenu> hiddenMenuList = children.stream().
                        filter(item -> !StringUtils.isEmpty(item.getComponent())).collect(Collectors.toList());
                for(SysMenu hiddenMenu : hiddenMenuList){
                    RouterVo hiddenRouter = new RouterVo();
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(),hiddenMenu.getIcon()));
                    routers.add(hiddenRouter);
                }
            }else {
                if (!CollectionUtils.isEmpty(children)){
                    if (children.size() > 0){
                        routerVo.setAlwaysShow(true);
                    }
                    routerVo.setChildren(buildRouter(children));
                }
            }
            routers.add(routerVo);
        }
        return routers;
    }

    @Override
    public List<String> findUserPermsByUserId(Long userId) {
        List<SysMenu> sysMenuList = null;
        //1.判断用户是否是管理员 userID = 1即为管理员
        if (userId == 1){
            //若是管理员则查询所有按钮列表
            sysMenuList = this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus,1));
        }else {
            //2.不是管理员，根据userid查询可操作按钮列表
            //多表关联查询，用户角色关系表，角色菜单关系表，菜单表
            sysMenuList = baseMapper.findMenuListByUserId(userId);

        }
        //3.从查询出来的数据里面，获取可以操作按钮值的list集合，返回
        List<String> perms = new ArrayList<>();
        for(SysMenu menu : sysMenuList){
            if(menu.getType() == 2){
                perms.add(menu.getPerms());
            }
        }
        return perms;
    }
    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = "/" + menu.getPath();
        if(menu.getParentId().intValue() != 0) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }
}
